package com.stray.crawl.exec;

import java.util.List;
import java.util.Map;
import java.util.Scanner;

import org.apache.commons.lang3.StringUtils;

import com.stray.crawl.BeanContext;
import com.stray.crawl.model.CrawlPlan;
import com.stray.crawl.model.PlanUrl;
import com.stray.crawl.model.dao.PlanRepository;
import com.stray.crawl.utils.DataUtils;
import com.stray.crawl.utils.ReflectUtils;
import com.stray.crawl.worker.TaskService;
import com.stray.crawl.worker.task.CrawlTask;

public class PlanTuner extends BeanContainer {

	private static final int COLUMN_WIDTH = 30;

	static CrawlPlan getNewPlan() {
		return null;
	}

	public static void main(String[] args) {
		run(new BeanCommand() {

			@Override
			public void execute(BeanContext ctx) throws Exception {
				String url = "http://www.uwants.com/forumdisplay.php?fid=554";
				Map<String, String> configs = DataUtils.toMap();
				Map<String, String> params = DataUtils.toMap();

				TaskService service = BeanContext.get(TaskService.class);

//				addPlan(ctx.getPlanRepository(), getNewPlan());

				// Test value
				Scanner scanner = null;

				try {
					scanner = new Scanner(System.in);

					CrawlTask task = service.newTask(url, configs, params);
					task.call();

					do {
						long usetime = System.currentTimeMillis();

						String[] fields = task.getTaskContext().getFields();
						String[] queries = task.getTaskContext().getQueries();

						ReflectUtils.invoke(task, "doParse");
						
						ReflectUtils.invoke(task, "doAction");

						printTask(task, usetime, COLUMN_WIDTH);

						System.out.print("Please enter the index to edit parser (0 to " + (fields.length - 1) + ") : ");
						String line = scanner.nextLine();

						if (StringUtils.isNumeric(StringUtils.substringBefore(line, ";"))) {
							int count = Integer.valueOf(StringUtils.substringBefore(line, ";"));

							if (count < queries.length) {
								queries[count] = StringUtils.substringAfter(line, ";");
							}
						} else if (!line.startsWith("r") && !line.startsWith("R")) {
							break ;
						}
						
					} while (true);
				} finally {
					if (scanner != null) {
						scanner.close();
					}
				}
			}

		});
	}

	private static void printTask(CrawlTask task, long usetime, int columnWidth) {
		String[] fields = task.getTaskContext().getFields();
		List<Object[]> results = task.getResultContext().getResults();

		System.out.print("\r\n");
		System.out.println("Plan Parser Query : " + task.getTaskContext().getExpress());
		int i = 0;
		for (String expr : task.getTaskContext().getQueries()) {
			System.out.println("> " + StringUtils.rightPad(fields[i], 30) + i++ + ";" + expr);
		}

		System.out.println(StringUtils.leftPad("", (columnWidth + 4) * fields.length, "="));

		for (String field : fields) {
			String str = String.format("| %s |", StringUtils.center(field, columnWidth));
			System.out.print(str);
		}

		System.out.print("\r\n");
		System.out.println(StringUtils.leftPad("", (columnWidth + 4) * fields.length, "="));

		for (Object[] objs : results) {
			for (Object obj : objs) {
				String str = obj.toString();
				str = str.replaceAll("\\n", "");
				str = StringUtils.substring(str, 0, columnWidth);
				str = String.format("| %s |", StringUtils.center(str, columnWidth));
				System.out.print(str);
			}
			System.out.print("\r\n");
		}

		System.out.println(StringUtils.leftPad("", (columnWidth + 4) * fields.length, "="));

		System.out.println(StringUtils.center("-- Size : " + results.size() + " / Time Used : " + (System.currentTimeMillis() - usetime) + "ms --", (columnWidth + 4) * fields.length));
	}

	@SuppressWarnings("unchecked")
	static void addPlan(PlanRepository repo, CrawlPlan plan) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		List<CrawlPlan> plans = (List<CrawlPlan>) ReflectUtils.getField(repo, "plans");
		plans.add(plan);

		Map<PlanUrl, CrawlPlan> map = (Map<PlanUrl, CrawlPlan>) ReflectUtils.getField(repo, "urlPlanMap");
		List<PlanUrl> urls = plan.getUrls();
		for (PlanUrl url : urls) {
			map.put(url, plan);
		}
	}

	@SuppressWarnings("unchecked")
	static void addGenericPlans(PlanRepository repo, CrawlPlan plan) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		List<CrawlPlan> plans = (List<CrawlPlan>) ReflectUtils.getField(repo, "genericPlans");
		plans.add(plan);
	}

}